import { Router } from 'express'
import { body, query, validationResult } from 'express-validator'
import { supabase } from '../server'
import { logger } from '../utils/logger'
import { asyncHandler, createError } from '../middleware/errorHandler'
import { AuthenticatedRequest, requireAdmin, logUserActivity } from '../middleware/auth'

const router = Router()

// Helper function to check validation results
const checkValidation = (req: any, res: any) => {
  const errors = validationResult(req)
  if (!errors.isEmpty()) {
    return res.status(400).json({
      success: false,
      message: 'Validation failed',
      errors: errors.array()
    })
  }
  return null
}

// Get user profile
router.get('/profile', 
  logUserActivity('view_profile'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const userId = req.user?.id

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const { data: profile, error } = await supabase
        .from('user_profiles')
        .select('*')
        .eq('user_id', userId)
        .single()

      if (error || !profile) {
        return res.status(404).json({
          success: false,
          message: 'User profile not found'
        })
      }

      // Remove sensitive information
      delete profile.gdpr_consent_date

      res.json({
        success: true,
        profile
      })

    } catch (error) {
      logger.error('Get profile error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Update user profile
router.put('/profile',
  [
    body('full_name').optional().trim().isLength({ min: 1, max: 100 }),
    body('display_name').optional().trim().isLength({ min: 1, max: 50 }),
    body('phone_number').optional().isMobilePhone('any')
  ],
  logUserActivity('update_profile'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const validationError = checkValidation(req, res)
    if (validationError) return validationError

    const userId = req.user?.id
    const { full_name, display_name, phone_number } = req.body

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const updateData: any = {
        updated_at: new Date().toISOString()
      }

      if (full_name !== undefined) updateData.full_name = full_name
      if (display_name !== undefined) updateData.display_name = display_name
      if (phone_number !== undefined) updateData.phone_number = phone_number

      const { data: profile, error } = await supabase
        .from('user_profiles')
        .update(updateData)
        .eq('user_id', userId)
        .select()
        .single()

      if (error) {
        logger.error('Profile update failed', { error: error.message, userId })
        throw createError('Profile update failed: ' + error.message, 400)
      }

      logger.info('Profile updated successfully', { userId, updates: Object.keys(updateData) })

      res.json({
        success: true,
        message: 'Profile updated successfully',
        profile
      })

    } catch (error) {
      logger.error('Update profile error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Update paper preferences
router.put('/preferences/papers',
  [
    body('categories').isArray(),
    body('keywords').isArray(),
    body('authors').optional().isArray(),
    body('institutions').optional().isArray()
  ],
  logUserActivity('update_paper_preferences'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const validationError = checkValidation(req, res)
    if (validationError) return validationError

    const userId = req.user?.id
    const { categories, keywords, authors, institutions } = req.body

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const paperPreferences = {
        categories: categories || [],
        keywords: keywords || [],
        authors: authors || [],
        institutions: institutions || []
      }

      const { data: profile, error } = await supabase
        .from('user_profiles')
        .update({
          paper_preferences: paperPreferences,
          updated_at: new Date().toISOString()
        })
        .eq('user_id', userId)
        .select()
        .single()

      if (error) {
        logger.error('Paper preferences update failed', { error: error.message, userId })
        throw createError('Preferences update failed: ' + error.message, 400)
      }

      logger.info('Paper preferences updated', { userId, categoriesCount: categories?.length })

      res.json({
        success: true,
        message: 'Paper preferences updated successfully',
        preferences: paperPreferences
      })

    } catch (error) {
      logger.error('Update paper preferences error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Update notification preferences
router.put('/preferences/notifications',
  [
    body('email_notifications').isBoolean(),
    body('weekly_digest').isBoolean(),
    body('instant_alerts').isBoolean(),
    body('paper_recommendations').isBoolean(),
    body('digest_frequency').isIn(['daily', 'weekly', 'monthly'])
  ],
  logUserActivity('update_notification_preferences'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const validationError = checkValidation(req, res)
    if (validationError) return validationError

    const userId = req.user?.id

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const { data: profile, error } = await supabase
        .from('user_profiles')
        .update({
          notification_preferences: req.body,
          updated_at: new Date().toISOString()
        })
        .eq('user_id', userId)
        .select()
        .single()

      if (error) {
        logger.error('Notification preferences update failed', { error: error.message, userId })
        throw createError('Notification preferences update failed: ' + error.message, 400)
      }

      logger.info('Notification preferences updated', { userId })

      res.json({
        success: true,
        message: 'Notification preferences updated successfully',
        preferences: req.body
      })

    } catch (error) {
      logger.error('Update notification preferences error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Update privacy settings
router.put('/preferences/privacy',
  [
    body('profile_visibility').isIn(['public', 'private', 'academic']),
    body('search_history_retention').isInt({ min: 0, max: 365 }),
    body('data_sharing_consent').isBoolean(),
    body('analytics_consent').isBoolean(),
    body('marketing_consent').isBoolean()
  ],
  logUserActivity('update_privacy_settings'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const validationError = checkValidation(req, res)
    if (validationError) return validationError

    const userId = req.user?.id

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const { data: profile, error } = await supabase
        .from('user_profiles')
        .update({
          privacy_settings: req.body,
          updated_at: new Date().toISOString()
        })
        .eq('user_id', userId)
        .select()
        .single()

      if (error) {
        logger.error('Privacy settings update failed', { error: error.message, userId })
        throw createError('Privacy settings update failed: ' + error.message, 400)
      }

      logger.info('Privacy settings updated', { userId, visibility: req.body.profile_visibility })

      res.json({
        success: true,
        message: 'Privacy settings updated successfully',
        settings: req.body
      })

    } catch (error) {
      logger.error('Update privacy settings error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Export user data (GDPR compliance)
router.get('/export',
  logUserActivity('export_data'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const userId = req.user?.id

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      // Get all user data
      const [profileResult, subscriptionResult, sessionResult, activityResult] = await Promise.all([
        supabase.from('user_profiles').select('*').eq('user_id', userId),
        supabase.from('subscriptions').select('*').eq('user_id', userId),
        supabase.from('user_sessions').select('*').eq('user_id', userId),
        supabase.from('user_activity_logs').select('*').eq('user_id', userId).limit(1000)
      ])

      const userData = {
        profile: profileResult.data?.[0],
        subscriptions: subscriptionResult.data,
        sessions: sessionResult.data,
        recent_activity: activityResult.data,
        export_date: new Date().toISOString(),
        data_retention_info: {
          profile: 'Retained for the life of the account',
          sessions: 'Retained for 90 days after expiration',
          activity_logs: 'Retained for 2 years'
        }
      }

      logger.info('User data exported', { userId })

      res.json({
        success: true,
        data: userData
      })

    } catch (error) {
      logger.error('Data export error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Delete user account (GDPR compliance)
router.delete('/account',
  [body('confirmEmail').isEmail()],
  logUserActivity('delete_account'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const validationError = checkValidation(req, res)
    if (validationError) return validationError

    const userId = req.user?.id
    const userEmail = req.user?.email
    const { confirmEmail } = req.body

    if (!userId || !userEmail) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    if (confirmEmail !== userEmail) {
      return res.status(400).json({
        success: false,
        message: 'Email confirmation does not match your account email'
      })
    }

    try {
      // Delete user data in correct order (respecting foreign key constraints)
      await Promise.all([
        supabase.from('user_sessions').delete().eq('user_id', userId),
        supabase.from('user_activity_logs').delete().eq('user_id', userId),
        supabase.from('subscriptions').delete().eq('user_id', userId)
      ])

      await supabase.from('user_profiles').delete().eq('user_id', userId)

      // Finally delete the auth user
      const { error } = await supabase.auth.admin.deleteUser(userId)
      if (error) {
        logger.error('Auth user deletion failed', { error: error.message, userId })
        throw createError('Account deletion failed: ' + error.message, 500)
      }

      logger.info('User account deleted', { userId, email: userEmail })

      res.json({
        success: true,
        message: 'Your account has been permanently deleted'
      })

    } catch (error) {
      logger.error('Account deletion error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Update GDPR consent
router.put('/consent/gdpr',
  [body('consent').isBoolean()],
  logUserActivity('update_gdpr_consent'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const validationError = checkValidation(req, res)
    if (validationError) return validationError

    const userId = req.user?.id
    const { consent } = req.body

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const { data: profile, error } = await supabase
        .from('user_profiles')
        .update({
          gdpr_consent: consent,
          gdpr_consent_date: consent ? new Date().toISOString() : null,
          updated_at: new Date().toISOString()
        })
        .eq('user_id', userId)
        .select()
        .single()

      if (error) {
        logger.error('GDPR consent update failed', { error: error.message, userId })
        throw createError('GDPR consent update failed: ' + error.message, 400)
      }

      logger.info('GDPR consent updated', { userId, consent })

      res.json({
        success: true,
        message: `GDPR consent ${consent ? 'granted' : 'revoked'} successfully`,
        consent: consent
      })

    } catch (error) {
      logger.error('Update GDPR consent error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Get user activity log
router.get('/activity',
  [
    query('page').optional().isInt({ min: 1 }),
    query('limit').optional().isInt({ min: 1, max: 100 })
  ],
  logUserActivity('view_activity_log'),
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const userId = req.user?.id
    const page = parseInt(req.query.page as string) || 1
    const limit = parseInt(req.query.limit as string) || 20
    const offset = (page - 1) * limit

    if (!userId) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      })
    }

    try {
      const [dataResult, countResult] = await Promise.all([
        supabase
          .from('user_activity_logs')
          .select('action, timestamp, ip_address, user_agent, request_path, request_method')
          .eq('user_id', userId)
          .order('timestamp', { ascending: false })
          .range(offset, offset + limit - 1),
        supabase
          .from('user_activity_logs')
          .select('id', { count: 'exact', head: true })
          .eq('user_id', userId)
      ])

      const activities = dataResult.data || []
      const totalCount = countResult.count || 0
      const totalPages = Math.ceil(totalCount / limit)

      res.json({
        success: true,
        activities,
        pagination: {
          current_page: page,
          total_pages: totalPages,
          total_items: totalCount,
          items_per_page: limit,
          has_next: page < totalPages,
          has_previous: page > 1
        }
      })

    } catch (error) {
      logger.error('Get activity log error', { 
        error: error instanceof Error ? error.message : String(error), 
        userId 
      })
      throw error
    }
  })
)

// Admin routes for user management
router.get('/admin/users',
  requireAdmin,
  [
    query('page').optional().isInt({ min: 1 }),
    query('limit').optional().isInt({ min: 1, max: 100 }),
    query('search').optional().trim(),
    query('status').optional().isIn(['active', 'inactive', 'suspended'])
  ],
  asyncHandler(async (req: AuthenticatedRequest, res) => {
    const page = parseInt(req.query.page as string) || 1
    const limit = parseInt(req.query.limit as string) || 20
    const offset = (page - 1) * limit
    const search = req.query.search as string
    const status = req.query.status as string

    try {
      let query = supabase
        .from('user_profiles')
        .select('user_id, email, full_name, display_name, subscription_status, created_at, last_login, is_active')

      if (search) {
        query = query.or(`email.ilike.%${search}%,full_name.ilike.%${search}%`)
      }

      if (status) {
        if (status === 'active') {
          query = query.eq('is_active', true)
        } else if (status === 'inactive') {
          query = query.eq('is_active', false)
        }
      }

      const [dataResult, countResult] = await Promise.all([
        query.order('created_at', { ascending: false }).range(offset, offset + limit - 1),
        query.select('user_id', { count: 'exact', head: true })
      ])

      const users = dataResult.data || []
      const totalCount = countResult.count || 0
      const totalPages = Math.ceil(totalCount / limit)

      res.json({
        success: true,
        users,
        pagination: {
          current_page: page,
          total_pages: totalPages,
          total_items: totalCount,
          items_per_page: limit,
          has_next: page < totalPages,
          has_previous: page > 1
        }
      })

    } catch (error) {
      logger.error('Admin get users error', { 
        error: error instanceof Error ? error.message : String(error)
      })
      throw error
    }
  })
)

export default router